const express = require('express');
const QRCode = require('qrcode');
const cors = require('cors');
const compression = require('compression');
const rateLimit = require('express-rate-limit');
const config = require('./config');
const mysql = require('mysql2/promise');

const app = express();

// 启用 gzip 压缩
if (config.PERFORMANCE.COMPRESSION) {
    app.use(compression());
}

// 设置并发限制
const limiter = rateLimit({
    windowMs: config.RATE_LIMIT.WINDOW_MS,
    max: config.RATE_LIMIT.MAX_REQUESTS,
    message: {
        code: -1,
        message: '请求过于频繁，请稍后再试'
    }
});
app.use(limiter);

// 基础中间件配置
app.use(express.json());
app.use(cors());

// 创建数据库连接池
const pool = mysql.createPool({
    host: config.DB.HOST,
    user: config.DB.USER,
    password: config.DB.PASSWORD,
    database: config.DB.DATABASE,
    waitForConnections: true,
    connectionLimit: 10,
    queueLimit: 0
});

// 字符映射表
const charMap = {
    '0': 'K', '1': 'L', '2': 'M', '3': 'N',
    '4': 'P', '5': 'Q', '6': 'R', '7': 'S',
    '8': 'T', '9': 'U', 'A': 'V', 'B': 'W',
    'C': 'X', 'D': 'Y', 'E': 'Z', 'F': 'H'
};

// 反向映射表
const reverseCharMap = Object.fromEntries(
    Object.entries(charMap).map(([k, v]) => [v, k])
);

// 工具函数：将ID转换为短码
const idToShortCode = (id) => {
    const hex = id.toString(16).toUpperCase();
    return hex.split('').map(char => charMap[char]).join('');
};

// 工具函数：将短码转换为ID
const shortCodeToId = (code) => {
    const hex = code.split('').map(char => reverseCharMap[char]).join('');
    return parseInt(hex, 16);
};

// 工具函数：检测设备类型
const isMobile = (userAgent) => {
    return /mobile|iphone|ipad|android/i.test(userAgent.toLowerCase());
};

// 生成中转链接
app.post(`${config.API_PREFIX}/generate_mid_url`, async (req, res) => {
    try {
        const { url } = req.body;
        
        // 输入验证
        if (!url) {
            return res.status(400).json({
                code: -1,
                message: '请提供有效的URL'
            });
        }
        
        // 插入URL到数据库
        const [result] = await pool.execute(
            'INSERT INTO linkurl (target) VALUES (?)',
            [url]
        );
        
        // 获取插入的ID并转换为短码
        const shortCode = idToShortCode(result.insertId);
        
        // 生成二维码
        const qrCode = await QRCode.toDataURL(url);
        
        res.json({
            code: 0,
            url_data: shortCode,
            qr_data: qrCode
        });
    } catch (error) {
        console.error('生成中转链接错误:', error);
        res.status(500).json({
            code: -1,
            message: '服务器内部错误'
        });
    }
});

// 解析目标URL
app.get(`${config.API_PREFIX}/set_target_url`, async (req, res) => {
    try {
        const { url } = req.query;
        const userAgent = req.headers['user-agent'];
        
        // 输入验证
        if (!url) {
            return res.status(400).json({
                code: -1,
                message: '请提供有效的短码'
            });
        }
        
        // 将短码转换为ID
        const id = shortCodeToId(url);
        
        // 从数据库查询URL
        const [rows] = await pool.execute(
            'SELECT target FROM linkurl WHERE id = ?',
            [id]
        );
        
        if (rows.length === 0) {
            return res.status(404).json({
                code: -1,
                message: '链接不存在'
            });
        }
        
        const originalUrl = rows[0].target;
        
        // 根据设备类型返回不同响应
        if (isMobile(userAgent)) {
            res.json({
                code: 0,
                data: originalUrl
            });
        } else {
            const qrCode = await QRCode.toDataURL(originalUrl);
            res.json({
                code: 1,
                data: qrCode
            });
        }
    } catch (error) {
        console.error('解析目标URL错误:', error);
        res.status(500).json({
            code: -1,
            message: '服务器内部错误'
        });
    }
});

// 错误处理中间件
app.use((err, req, res, next) => {
    console.error('全局错误处理:', err);
    res.status(500).json({
        code: -1,
        message: '服务器内部错误'
    });
});

// 启动服务器
app.listen(config.PORT, () => {
    console.log(`服务器运行在端口 ${config.PORT}`);
});

module.exports = app;